package genome;

import java.io.Serializable;
import java.util.ArrayList;

import tool.Utility;

//Very abstract genotype class, contains the basic methods and constructs, should be extended to the desired representation

public abstract class Genotype implements Comparable<Genotype>, Serializable{

protected double[] input;
public int[] genome;
public int size;

public double RELATIVE_FITNESS;
	
	public Genotype(double[] in, int sz){
		this.input = in;
		this.size = sz;
		this.genome = new int[this.size];
		
		RELATIVE_FITNESS = 0.0;
	}
	public void clear(int x){
		//zeros current genome up to x
		for (int i = 0; (i < x && i< genome.length); i++) {
			genome[i] = 0;
		}
	}
	public void printInput(){
		for(int i=0; i<input.length; i++){System.out.print(input[i]); System.out.println("");}
	}
	
	public void printGenome(){
		for(int i=0; i<genome.length; i++){System.out.print(genome[i]+" ");}
		 System.out.println("");
	}
	
	public String toString(){
		String s = ""; for(int i=0; i<genome.length; i++){s+=genome[i]+" ";}
		return s;
	}
	
	public boolean equals(Genotype g){
		boolean sameGenome = false;
		if(g instanceof Genotype && g.size == this.size){
			sameGenome = true;
			for(int i=0; i<genome.length; i++){if(g.genome[i]!=this.genome[i]){sameGenome=false;}}
		}
		return sameGenome;
	}
	
	public void setInput(double[] pinput){
		this.input = pinput;
	}
	
	public double getRELATIVE_FITNESS() {
		return RELATIVE_FITNESS;
	}

	public void setRELATIVE_FITNESS(double pRELATIVEFITNESS) {
		this.RELATIVE_FITNESS = pRELATIVEFITNESS;
	}

	public double[] getInput() {
		return input;
	}
	

	public abstract Genotype getCopy();
	
	public int compareTo(Genotype g){
		if(g.RELATIVE_FITNESS>this.RELATIVE_FITNESS){return -1;}
		else{
			if(g.RELATIVE_FITNESS == this.RELATIVE_FITNESS){return 0;}
			else{return 1;}
		}
	}

	public int[] getGenome() {
		return genome;
	}

	public void setGenome(int[] genome) {
		this.genome = genome;
	}
	
	public int hashCode(){
		String s = Utility.intArrayToString(this.genome);
		return s.hashCode(); //hashes based upon string of genome
	}
	
	public int diff(Genotype g){
		//returns -1 if not equal in length to other genome, otherwise returns number of different genes.
		
		int d = 0;
		
		if(g.size != this.size){
			d = -1;
		}
		else {
			for(int i=0;i<size;i++){
				if(this.genome[i]!=g.genome[i]){
					d++;
				}
			}
		}
		return d;
	}
	
	public abstract Genotype increment();
	
	public abstract ArrayList<Genotype> generateSpace();
	
	public abstract Genotype pointMutate();
	
	public abstract String toMathString();
	
	public abstract String getConstantString();
	
	public abstract void setConstants(double[] d);
	
	public abstract double eval();
	
	public abstract Genotype stoMutate();
	
	public abstract int[] toVector();

}
